package com.joolun.weixin.handler.tp;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.joolun.common.constant.Constants;
import com.joolun.common.utils.DateUtils;
import com.joolun.common.utils.uuid.IdUtils;
import com.joolun.system.domain.*;
import com.joolun.system.service.IEduSchedulingService;
import com.joolun.system.service.impl.SysCorpConfigServiceImpl;
import com.joolun.weixin.builder.cp.TextBuilder;
import com.joolun.weixin.config.WxCpConfiguration;
import com.joolun.weixin.entity.WxGroupChat;
import com.joolun.weixin.entity.dto.WxCpXmlOutMessageDTO;
import com.joolun.weixin.handler.CpAbstractHandler;
import com.joolun.weixin.service.*;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpExternalContactServiceImpl;
import me.chanjar.weixin.cp.bean.external.WxCpGroupJoinWayInfo;
import me.chanjar.weixin.cp.bean.external.WxCpGroupJoinWayResult;
import me.chanjar.weixin.cp.bean.external.contact.FollowedUser;
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
import me.chanjar.weixin.cp.constant.WxCpConsts;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/***
 * 客户群事件推送回调事件
 * @author xuxh
 * @date 2022/4/28 17:27
 */
@Slf4j
@Service(WxCpConsts.EventType.CHANGE_EXTERNAL_CHAT)
public class WxChangeExternalChatEventHandler extends CpAbstractHandler {


    @Autowired
    @Lazy
    private IWxGroupChatService groupChatService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private IBrCustomerDynamicService customerDynamicService;

    @Autowired
    private IEduSchedulingClassService eduSchedulingClassService;

    @Autowired
    private IEduSchedulingService eduSchedulingService;

    @Autowired
    private IScrmCustomerInfoService iScrmCustomerInfoService;
    @Autowired
    private IScrmChannelRecordLogService scrmChannelRecordLogService;
    @Autowired
    private IScrmChannelStatisticsService scrmChannelStatisticsService;

    @Autowired
    private SysCorpConfigServiceImpl sysCorpConfigService;


    @Override
    public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> map, WxCpService wxCpTpService, WxSessionManager wxSessionManager) throws WxErrorException {
        WxCpXmlOutMessageDTO dto = new WxCpXmlOutMessageDTO();
        BeanUtils.copyProperties(wxMessage, dto);
        dto.setExtCorpId(wxCpTpService.getWxCpConfigStorage().getCorpId());
        log.debug("群聊相关mq发送：[{}], [{}]", wxMessage.getChangeType(), JSON.toJSONString(dto));
        //修改群聊
        if (Constants.WX_CHANGE_TYPE_UPDATE.equals(wxMessage.getChangeType())) {
            //发送MQ异步处理
            String updateDetail = (String) wxMessage.getAllFieldsMap().get("UpdateDetail");
            List<String> updateDetailInfos = Arrays.asList(Constants.WX_UPDATE_DETAIL_CHANGE_OWNER, Constants.WX_UPDATE_DETAIL_CHANGE_NAME, Constants.WX_UPDATE_DETAIL_CHANGE_NOTICE);
            //如果都是修改了详情数据，发同一个队列中
            if (updateDetailInfos.contains(updateDetail)) {
                rabbitTemplate.convertAndSend(Constants.WX_UPDATE_DETAIL, dto);
            } else {
                rabbitTemplate.convertAndSend(updateDetail, dto);
            }
        } else {
            rabbitTemplate.convertAndSend(wxMessage.getChangeType(), dto);
        }

        try {
            String content = "感谢反馈，您的信息已收到！";
            return new TextBuilder().build(content, wxMessage, null);
        } catch (Exception e) {
            log.error("联系人变更消息接收异常", e);
            return null;
        }
    }


    /**
     * 监听事件: 成员退群
     *
     * @param dto 消息
     * @author xuxh
     * @date 2022/2/16 10:29
     */
    @RabbitListener(queues = Constants.WX_UPDATE_DETAIL_DEL_MEMBER)
    @Transactional(rollbackFor = Exception.class)
    public void updateDetailDelMemberListener(WxCpXmlOutMessageDTO dto) {
        String str = IdUtils.get32UUID();
        log.info("消费MQ:[del_member],事件描述:[成员退群],编号:[{}],企业ID:[{}],message[{}]", str, dto.getExtCorpId(), JSON.toJSONString(dto));
        try {
            // 获取主体配置
            SysCorpConfig sysCorpConfig = sysCorpConfigService.getConfig(dto.getExtCorpId());
            WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getWxCpService(sysCorpConfig));
            WxGroupChat wxGroupChat = groupChatService.saveOrUpdate(dto.getExtCorpId(), dto.getChatId(), null, externalContactService);

            String dtoJsonData = JSON.toJSONString(dto.getAllFieldsMap());
            //客户动态
            customerDynamicService.saveByQueue(WxCpConsts.ExternalChatChangeType.ExternalChatUpdateDetail.DEL_MEMBER, dto.getExtCorpId(), dto.getUserId(), dto.getExternalUserId(), dtoJsonData);
            String staffId = wxGroupChat.getOwner();

            //{"Item":["wmZKj2EAAASno_YCAMAV544MAkNt3nQw"]}
            String memchangeList = JSONObject.parseObject(dtoJsonData).getString("MemChangeList");
            JSONArray jsonArray = JSONObject.parseObject(memchangeList).getJSONArray("Item");
            String extCustomerId =  jsonArray.get(0).toString();

            ScrmCustomerInfo scrmCustomerInfo = iScrmCustomerInfoService.getOne(Wrappers.lambdaQuery(ScrmCustomerInfo.class)
                    .eq(ScrmCustomerInfo::getExtCustomerId,extCustomerId)
                    .eq(ScrmCustomerInfo::getExtStaffId,staffId).eq(ScrmCustomerInfo::getExtCorpId,wxGroupChat.getExtCorpId()));

            Long planId = scrmCustomerInfo.getPlanId();
            if(planId != null){
                // 更新统计数据
                ScrmChannelStatistics scrmChannelStatistics = scrmChannelStatisticsService.getOne(Wrappers.lambdaQuery(ScrmChannelStatistics.class).eq(ScrmChannelStatistics::getPlanId,scrmCustomerInfo.getPlanId()));
                if(scrmChannelStatistics != null){
                    scrmChannelStatistics.setSyNum(scrmChannelStatistics.getSyNum() +1);
                    scrmChannelStatisticsService.saveOrUpdate(scrmChannelStatistics);
                }
                // 添加行为记录-退群
                scrmChannelRecordLogService.changeFriend(scrmCustomerInfo,"QuitGroup");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("消费MQ异常:[del_member],事件描述:[成员退群],编号:[{}],企业ID:[{}],message[{}],异常原因:[{}],异常描述:[{}]", str, dto.getExtCorpId(), dto, "系统异常", e);
        }
    }

    /**
     * 监听事件: 成员入群
     *
     * @param dto 消息
     * @author xuxh
     * @date 2022/2/16 10:29
     */
    @RabbitListener(queues = Constants.WX_UPDATE_DETAIL_ADD_MEMBER)
    @Transactional(rollbackFor = Exception.class)
    public void updateDetailAddMemberListener(WxCpXmlOutMessageDTO dto) {
        String str = IdUtils.get32UUID();
        log.info("消费MQ:[add_member],事件描述:[成员入群],编号:[{}],企业ID:[{}],message[{}]", str, dto.getExtCorpId(), dto);
        try {
            // 获取主体配置
            SysCorpConfig sysCorpConfig = sysCorpConfigService.getConfig(dto.getExtCorpId());
            WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getWxCpService(sysCorpConfig));
            WxGroupChat wxGroupChat = groupChatService.saveOrUpdate(dto.getExtCorpId(), dto.getChatId(), null, externalContactService);
            String dtoJsonData = JSON.toJSONString(dto.getAllFieldsMap());

            // 客户动态
            customerDynamicService.saveByQueue(WxCpConsts.ExternalChatChangeType.ExternalChatUpdateDetail.DEL_MEMBER, dto.getExtCorpId(), dto.getUserId(), dto.getExternalUserId(), dtoJsonData);
            //TODO： 更新入群数
            String staffId = wxGroupChat.getOwner();

            //{"Item":["wmZKj2EAAASno_YCAMAV544MAkNt3nQw"]}
            String memchangeList = JSONObject.parseObject(dtoJsonData).getString("MemChangeList");
            JSONArray jsonArray = JSONObject.parseObject(memchangeList).getJSONArray("Item");
            String extCustomerId =  jsonArray.get(0).toString();

            ScrmCustomerInfo scrmCustomerInfo = iScrmCustomerInfoService.getOne(Wrappers.lambdaQuery(ScrmCustomerInfo.class)
                    .eq(ScrmCustomerInfo::getExtCustomerId,extCustomerId)
                    .eq(ScrmCustomerInfo::getExtStaffId,staffId).eq(ScrmCustomerInfo::getExtCorpId,wxGroupChat.getExtCorpId()));

            Long planId = scrmCustomerInfo.getPlanId();
            if(planId != null){
                // 更新统计数据
                ScrmChannelStatistics scrmChannelStatistics = scrmChannelStatisticsService.getOne(Wrappers.lambdaQuery(ScrmChannelStatistics.class).eq(ScrmChannelStatistics::getPlanId,scrmCustomerInfo.getPlanId()));
                if(scrmChannelStatistics != null){
                    scrmChannelStatistics.setSyNum(scrmChannelStatistics.getSyNum() +1);
                    scrmChannelStatisticsService.saveOrUpdate(scrmChannelStatistics);
                }
                // 添加行为记录-入群
                scrmChannelRecordLogService.changeFriend(scrmCustomerInfo,"JoinGroup");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("消费MQ异常:[add_member],事件描述:[成员入群],编号:[{}],企业ID:[{}],message[{}],异常原因:[{}],异常描述:[{}]", str, dto.getExtCorpId(), dto, "系统异常", e);
        }
    }


    /**
     * 监听事件: 群公告变更
     *
     * @param dto 消息
     * @author xuxh
     * @date 2022/2/16 10:29
     */
    @RabbitListener(queues = Constants.WX_UPDATE_DETAIL)
    @Transactional(rollbackFor = Exception.class)
    public void updateDetailChangeNoticeListener(WxCpXmlOutMessageDTO dto) {
        String str = IdUtils.get32UUID();
        log.info("消费MQ:[change_detail],事件描述:[群详情变更],编号:[{}],企业ID:[{}],message[{}]", str, dto.getExtCorpId(), dto);
        try {
            WxGroupChat groupChat = groupChatService.getOne(new LambdaQueryWrapper<WxGroupChat>()
                    .eq(WxGroupChat::getExtCorpId, dto.getExtCorpId())
                    .eq(WxGroupChat::getExtChatId, dto.getChatId())
            );

            //修改详情信息
            if (groupChat != null) {
                // 获取主体配置
                SysCorpConfig sysCorpConfig = sysCorpConfigService.getConfig(dto.getExtCorpId());
                WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getCustomerSecretWxCpService(sysCorpConfig));
                groupChatService.saveOrUpdate(dto.getExtCorpId(), dto.getChatId(), WxGroupChat.STATUS_NORMAL, externalContactService);
            }
        } catch (WxErrorException e) {
            e.printStackTrace();
            log.error("消费MQ异常:[change_detail],事件描述:[群详情变更],编号:[{}],企业ID:[{}],message[{}],异常原因:[{}],异常描述:[{}]", str, dto.getExtCorpId(), dto, "调用企业微信接口异常", e);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("消费MQ异常:[change_detail],事件描述:[群详情变更],编号:[{}],企业ID:[{}],message[{}],异常原因:[{}],异常描述:[{}]", str, dto.getExtCorpId(), dto, "系统异常", e);
        }
    }

    /**
     * 监听事件: 新增群聊
     *
     * @param dto 消息
     * @author xuxh
     * @date 2022/2/16 10:29
     */
    @RabbitListener(queues = Constants.WX_CHANGE_TYPE_CREATE)
    @Transactional(rollbackFor = Exception.class)
    public void createGroupChat(WxCpXmlOutMessageDTO dto) {
        String str = IdUtils.get32UUID();
        log.info("消费MQ:[create],事件描述:[新增群聊],编号:[{}],企业ID:[{}],message[{}]", str, dto.getExtCorpId(), dto);
        try {
            // 获取主体配置
            SysCorpConfig sysCorpConfig = sysCorpConfigService.getConfig(dto.getExtCorpId());
            WxGroupChat groupChat = groupChatService.getOne(new LambdaQueryWrapper<WxGroupChat>()
                    .eq(WxGroupChat::getExtCorpId, dto.getExtCorpId())
                    .eq(WxGroupChat::getExtChatId, dto.getChatId())
            );
            //新增群聊
            if (groupChat == null) {
                WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getCustomerSecretWxCpService(sysCorpConfig));
                groupChatService.saveOrUpdate(dto.getExtCorpId(), dto.getChatId(), null, externalContactService);
            }
            String extChatId = groupChat.getExtChatId();
            String owner = groupChat.getOwner();
            //TODO： 查找群主当前有效的排期信息，如果没有则后置绑定

            String state = IdUtils.get16UUID();


            List<EduScheduling> eduSchedulingList = eduSchedulingService.list(Wrappers.lambdaQuery(EduScheduling.class)
                    //.eq(EduScheduling::getSchedulingId,schedulingId)
                    .lt(EduScheduling::getEnrollStartTime, DateUtils.getNowDate())
                    .gt(EduScheduling::getEnrollEndTime, DateUtils.getNowDate())
                    .orderByAsc(EduScheduling::getEnrollStartTime));
            if(CollectionUtil.isNotEmpty(eduSchedulingList)){
                List<Long> ids = eduSchedulingList.stream().map(item->item.getSchedulingId()).collect(Collectors.toList());
                EduSchedulingClass eduSchedulingClass = eduSchedulingClassService.getOne(Wrappers.lambdaQuery(EduSchedulingClass.class).eq(EduSchedulingClass::getWecomId,owner)
                        .in(EduSchedulingClass::getSchedulingId,ids));
                if(eduSchedulingClass !=null ){
                    // 招生排期ID
                    Long schedulingId = eduSchedulingClass.getSchedulingId();
                    state = schedulingId.toString();

                }
            }
            // 配置客户群进群方式，设置state
            WxCpGroupJoinWayInfo wxCpGroupJoinWayInfo = new WxCpGroupJoinWayInfo();
            WxCpGroupJoinWayInfo.JoinWay joinWay = new WxCpGroupJoinWayInfo.JoinWay();
            // 场景:1 - 群的小程序插件,2 - 群的二维码插件
            joinWay.setScene(2);
            joinWay.setChatIdList(Collections.singletonList(extChatId));
            joinWay.setState(state);
            wxCpGroupJoinWayInfo.setJoinWay(joinWay);
            // 配置客户群进群方式
            WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getCustomerSecretWxCpService(sysCorpConfig));
            WxCpGroupJoinWayResult wxCpGroupJoinWayResult = externalContactService.addJoinWay(wxCpGroupJoinWayInfo);

            groupChat.setConfigId( wxCpGroupJoinWayResult.getConfigId());
            groupChat.setState(state);
            groupChatService.updateById(groupChat);

        } catch (WxErrorException e) {
            e.printStackTrace();
            log.error("消费MQ异常:[create],事件描述:[新增群聊],编号:[{}],企业ID:[{}],message[{}],异常原因:[{}],异常描述:[{}]", str, dto.getExtCorpId(), dto, "调用企业微信接口异常", e);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("消费MQ异常:[create],事件描述:[新增群聊],编号:[{}],企业ID:[{}],message[{}],异常原因:[{}],异常描述:[{}]", str, dto.getExtCorpId(), dto, "系统异常", e);
        }
    }

    /**
     * 监听事件: 解散群聊
     *
     * @param dto 消息
     * @author xuxh
     * @date 2022/2/16 10:29
     */
    @RabbitListener(queues = WxCpConsts.ExternalChatChangeType.DISMISS)
    @Transactional(rollbackFor = Exception.class)
    public void dismissGroupChat(WxCpXmlOutMessageDTO dto) {
        String str = IdUtils.get32UUID();
        log.info("消费MQ:[dismiss],事件描述:[解散群聊],编号:[{}],企业ID:[{}],message[{}]", str, dto.getExtCorpId(), dto);
        try {
            groupChatService.delete(dto.getExtCorpId(), dto.getChatId());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("消费MQ异常:[dismiss],事件描述:[解散群聊],编号:[{}],企业ID:[{}],message[{}],异常原因:[{}],异常描述:[{}]", str, dto.getExtCorpId(), dto, "系统异常", e);
        }
    }

}
